'''
Created on Feb 29, 2012

@author: Johnathon
'''

from LineValues import X, Zero, One, D, DNot 
import sys

class Wire(object):
    '''
    classdocs
    '''
    def __init__(self, name = "", level = -1, fromLineOrGate = None, toLinesAndGates = -1, lineNum = -1):
        '''
        Constructor
        '''
        self.name = name
        self.source = fromLineOrGate
        self.destinations = []
        self.value = X
        self.level = level
        self.lineNum = lineNum
        self.isStuck = False
        self.zeroControllability = sys.maxint
        self.oneControllability = sys.maxint
        self.observability = sys.maxint
        self.exhasuted = False #Exhasuted means that it's not possible to propagate the D Frontier through this wire
        self.stuckValue = None 

        if type(toLinesAndGates) is list:
            self.destinations = toLinesAndGates

    def setStuckAt(self, stuckAtValue):
        if stuckAtValue is not Zero and stuckAtValue is not One:
            raise AttributeError("Tried to set a line to be stuck at an invalid signal.")
        if stuckAtValue is None:
            self.isStuck = False
        else:
            self.isStuck = True
            self.stuckValue = stuckAtValue 

    def driveValue(self, value):
        if not value.isLineValue():
            raise AttributeError("Tried to assign invalid signal to a line.")

        self.value = value
        if self.isStuck: 
            if value is One and self.stuckValue is Zero: 
                self.value = D
            elif value is Zero and self.stuckValue is One:
                self.value = DNot 
        for destination in self.destinations:
            if type(destination) is Wire:
                destination.driveValue(self.value)
        
    def __repr__(self):
        return self.name + ": " + str(self.value)

    def printSelf(self):
        inputName = ""
        outputNames = ""
        
        if self.source != None:
            inputName = str(self.source.name)
        else: 
            inputName = "Primary Input"

        for count in range(len(self.destinations)):
            outputNames += str(self.destinations[count].name) + ', ' 

        outputNames = outputNames.strip(', ')

        pval = "Huh?"
        if self.value is X: 
            pval = "X"
        elif self.value is One: 
            pval = "One"
        elif self.value is Zero: 
            pval = "Zero"
        elif self.value is D: 
            pval = "D"
        elif self.value is DNot: 
            pval = "DNot"

        psValue = "Not stuck"
        if self.isStuck == True: 
            if self.stuckValue is One: 
                psValue = "One"
            else: 
                psValue = "Zero"

        print "----------"
        print self.name
        print "Input: " + inputName
        print "Outputs: " + outputNames 
        print "Value: " + pval 
        print "Level: " + str(self.level) 
        print "observability: " + str(self.observability)
        print "One Controllability: " + str(self.oneControllability)
        print "Zero Controllability: " + str(self.zeroControllability)
        print "Stuck at value: " + psValue 
        print "----------"